﻿using DataModels.Dto;
using DataModels.Dto.OfflineStore;
using DataModels.Entities.AuthCore;
using DataModels.Entities.OfflineStore;
using DataModels.Enums.Bill;
using DataModels.Enums.OfflineStore;
using SqlSugar;
using Utils;
using static DataModels.Enums.GeneralEnum;

namespace Services.OfflineStore
{
    public class OfflineStoreService(SqlSugarClient db):BaseService(db)
    {
        /// <summary>
        /// 获取所有商品分类
        /// </summary>
        /// <returns></returns>
        public async Task<ResponseModel> GetOfflineStoreProductCategories()
        {
            List<OfflineStoreProductCategory> ospc =  await db.Queryable<OfflineStoreProductCategory>()
                .Where(x => x.UUID != Guid.Empty)
                .ToListAsync();
            return Success(ospc);
        }

        /// <summary>
        /// 获取商品列表
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<ResponseModel> GetOfflineStoreProduct(GetOfflineStoreProductInfo info)
        {
            RefAsync<int> total = 0;
            List<GetOfflineStoreProductDto> osp = await db.Queryable<OfflineStoreProduct, OfflineStoreStore>((osp,oss) => new JoinQueryInfos(
                    JoinType.Left, osp.OfflineStoresStoreUUID == oss.UUID
                ))
                .Where(osp => osp.IsDeleted == Status.Disable)
                .Where(osp => osp.Status == Status.Enable)
                .WhereIF(info.IsRecommend.HasValue,osp => osp.IsRecommend == info.IsRecommend)
                .WhereIF(info.OfflineStoreProductCategoryUUID.HasValue,osp => osp.OfflineStoreProductCategoryUUID == info.OfflineStoreProductCategoryUUID)
                .Select((osp, oss) => new GetOfflineStoreProductDto
                {
                    UUID = osp.UUID,
                    ImageUrl = osp.ImageUrl,
                    Latitude = oss.Latitude,
                    Longitude = oss.Longitude,
                    Title = osp.Title,
                    Price = osp.Price,
                    OriginalPrice = osp.OriginalPrice,
                    LogoUrl = oss.LogoUrl,
                    Name = oss.Name
                })
                .ToPageListAsync(info.PageNumber, info.PageSize, total);


            return PageSuccess(info.PageNumber, info.PageSize, total,osp);
        }

        /// <summary>
        /// 获取商品详情
        /// </summary>
        /// <param name="uuid"></param>
        /// <returns></returns>
        public async Task<ResponseModel> GetOfflineStoreProductDetail(Guid uuid)
        {
            var osp = await db.Queryable<OfflineStoreProduct, OfflineStoreStore>((osp, oss) => new JoinQueryInfos(
                    JoinType.Left, osp.OfflineStoresStoreUUID == oss.UUID
                ))
                .Where(osp => osp.UUID == uuid && osp.IsDeleted == Status.Disable && osp.Status == Status.Enable)
                .Select((osp, oss) => new GetOfflineStoreProductDetail
                {
                    OfflineStoreProductUUID = osp.UUID,
                    ImageUrl = osp.ImageUrl,
                    Title = osp.Title,
                    Price = osp.Price,
                    OriginalPrice = osp.OriginalPrice,
                    OfflineStoreStoreUUID = oss.UUID,
                    LogoUrl = oss.LogoUrl,
                    Name = oss.Name,
                    BusinessHours = oss.BusinessHours,
                    PhoneNumber = oss.PhoneNumber,
                    Address = oss.Address,
                    Latitude = oss.Latitude,
                    Longitude = oss.Longitude,
                })
                .FirstAsync();

            if (osp == null)
            {
                return Error("商品不存在或已被删除");
            }

           osp.ImageUrls =GetAttachment(osp.OfflineStoreProductUUID);
            return Success(osp);
        }

        /// <summary>
        /// 提交订单
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<ResponseModel> SubmitOfflineStoreOrder(SubmitOfflineStoreOrderInfo info)
        {
            try
            {

                await db.BeginTranAsync();

                // 检查商品是否存在
                OfflineStoreProduct osp = await db.Queryable<OfflineStoreProduct>()
                    .Where(osp => osp.UUID == info.OfflineStoreProductUUID && osp.IsDeleted == Status.Disable && osp.Status == Status.Enable)
                    .FirstAsync();

                if (osp == null)
                {
                    await db.RollbackTranAsync();
                    return Success("商品不存在或已下架");
                }
                if (osp.Count < info.Count)
                {
                    await db.RollbackTranAsync();
                    return Error("库存不足");
                }
                decimal DiscountAmount = 0;
                decimal OrderAmount = osp.Price * info.Count;
                Guid? PaymentCouponMapUUID = null;
                if (info.PaymentCouponUUID.HasValue)
                {
                    PaymentCouponMap pcm = await db.Queryable<PaymentCouponMap>()
                        .Where(pcm => pcm.UUID == info.PaymentCouponUUID)
                        .Where(pcm => pcm.IsDeleted == Status.Disable)
                        .Where(pcm => pcm.IsUsed == Status.Disable)
                        .Where(pcm => pcm.EndTime > DateTime.Now)
                       .FirstAsync();
                    if (pcm == null)
                    {
                        await db.RollbackTranAsync();
                        return Error("优惠券不存在或已过期");
                    }
                    if (pcm.Type != PaymentCouponType.OfflineStore)
                    {
                        await db.RollbackTranAsync();
                        return Error("该优惠卷不允许在此订单中使用，请查看优惠券类型");
                    }
                    PaymentCouponMapUUID = pcm.UUID;
                    pcm.IsUsed = Status.Enable;
                    pcm.UpdateUserUUID = UserUUID;
                    pcm.UpdateTime = DateTime.Now;
                    await db.Updateable(pcm).ExecuteCommandAsync();

                    if (pcm.Price > OrderAmount)
                    {
                        DiscountAmount = OrderAmount;
                    }
                    else
                    {
                        DiscountAmount = pcm.Price;
                    }
                }

                OfflineStoreOrderTotal ordert = new()
                {
                    OfflineStoreProductUUID = osp.UUID,
                    OrderAmount = OrderAmount,
                    DiscountAmount = DiscountAmount,
                    PaymentCouponMapUUID = PaymentCouponMapUUID,
                    ContactPerson = info.ContactPerson,
                    ContactGender = info.ContactGender,
                    ContactPhone = info.ContactPhone,
                    CreateUserUUID = UserUUID
                };

                ordert = await db.Insertable(ordert).ExecuteReturnEntityAsync();

                if (ordert == null)
                {
                    await db.RollbackTranAsync();
                    return Error("订单创建失败，请稍后重试");
                }

                //拆分优惠
                decimal[] ItemDiscountAmount = AllocateDiscountByAverage(DiscountAmount, info.Count);

                for (int i = 0; i < info.Count; i++)
                {
                    OfflineStoreOrder order = new()
                    {
                        OfflineStoreOrderTotalUUID = ordert.UUID,
                        OfflineStoreProductUUID = osp.UUID,
                        OrderAmount = osp.Price,
                        DiscountAmount = ItemDiscountAmount[i],
                        PaymentCouponMapUUID = PaymentCouponMapUUID,
                        CreateUserUUID = UserUUID
                    };
                    var result = await db.Insertable(order).ExecuteReturnEntityAsync();
                    if (result == null)
                    {
                        await db.RollbackTranAsync();
                        return Error("订单详情创建失败，请稍后重试");
                    }
                }

                osp.Count -= info.Count;

                await db.Updateable(osp).ExecuteCommandAsync();

                await db.CommitTranAsync();

                return Success(ordert);
            }
            catch (Exception ex)
            {
                await db.RollbackTranAsync();
                return Error("订单提交失败");
            }
        }

        /// <summary>
        /// 订单支付
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<ResponseModel> OfflineStoreOrderPayment(OfflineStoreOrderPaymentInfo info)
        {
            try
            {
                await db.BeginTranAsync();

                OfflineStoreOrderTotal osot = await db.Queryable<OfflineStoreOrderTotal>()
                    .Where(osot => osot.IsDeleted == Status.Disable)
                    .Where(osot => osot.ExpireTime > DateTime.Now)
                    .Where(osot => osot.CreateUserUUID == UserUUID)
                    .Where(osot => osot.OrderStatus == OfflineStoreOrderStatus.PendingPayment)
                    .Where(osot => osot.UUID == info.OfflineStoreOrderUUID)
                    .FirstAsync()
                    ;
                if(osot == null)
                {
                    await db.RollbackTranAsync();
                    return Error("未找到待支付的订单，请检查订单状态");
                }

                //处理总订单

                //未实现逻辑，默认全额付款 - 优惠
                osot.PayAmount = osot.OrderAmount - osot.DiscountAmount;
                osot.OrderStatus = OfflineStoreOrderStatus.Paid;
                osot.UpdateTime = DateTime.Now;
                osot.UpdateUserUUID = UserUUID;

                List<OfflineStoreOrder> osos = await db.Queryable<OfflineStoreOrder>()
                    .Where(oso => oso.IsDeleted == Status.Disable)
                    .Where(oso => oso.OrderStatus == OfflineStoreOrderStatus.PendingPayment)
                    .Where(oso => oso.OfflineStoreOrderTotalUUID == osot.UUID)
                    .ToListAsync()
                    ;

                //处理子订单
                //未实现逻辑，默认全额付款 - 优惠
                foreach (var oso in osos)
                {
                    oso.PayAmount = oso.OrderAmount - oso.DiscountAmount;
                    oso.OrderStatus = OfflineStoreOrderStatus.Paid;
                    oso.UpdateTime = DateTime.Now;
                    oso.UpdateUserUUID = UserUUID;

                    await db.Updateable(oso).ExecuteCommandAsync();
                }
                await db.Updateable(osot).ExecuteCommandAsync();

                await db.CommitTranAsync();
                return Success("付款逻辑未实现，所有请求默认付款完成");
            }
            catch
            {
                await db.RollbackTranAsync();
                return Error("付款失败");
            }

        }

        /// <summary>
        /// 获取到店订单
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<ResponseModel> GetOrder(GetOrderInfo info)
        {
            RefAsync<int> total = 0;

            var data = await db.Queryable<OfflineStoreOrderTotal>()
                    .Where(osot => osot.IsDeleted == Status.Disable)
                    .Where(osot => osot.CreateUserUUID == UserUUID)
                    .WhereIF(info.OrderStatus.HasValue, osot => osot.OrderStatus == info.OrderStatus)
                    .ToPageListAsync(info.PageNumber, info.PageSize, total)
                    ;

            List<Guid> uuids = [.. data.Select(x => x.UUID)];

            List<OfflineStoreOrder> orders = await db.Queryable<OfflineStoreOrder>()
                .Where(oso => uuids.Contains(oso.OfflineStoreOrderTotalUUID))
                .Where(oso => oso.IsDeleted == Status.Disable)
                .Where(oso => oso.CreateUserUUID == UserUUID)
                .WhereIF(info.OrderStatus.HasValue, oso => oso.OrderStatus == info.OrderStatus)
                .ToListAsync()
                ;

            foreach (var item in data)
            {
                item.Orders = [.. orders.Where(x => x.OfflineStoreOrderTotalUUID == item.UUID)];
            }

            return PageSuccess(info.PageNumber, info.PageSize, total, data);
        }


        /// <summary>
        /// 平均分配优惠金额到多个商品
        /// </summary>
        /// <param name="totalDiscount">总优惠金额(元)</param>
        /// <param name="productCount">商品数量</param>
        /// <returns>每个商品的优惠金额数组</returns>
        /// <summary>
        /// 平均分配优惠金额到多个商品，余数全部加到最后一个商品
        /// </summary>
        /// <param name="totalDiscount">总优惠金额(元)</param>
        /// <param name="productCount">商品数量</param>
        /// <returns>每个商品的优惠金额数组</returns>
        private static decimal[] AllocateDiscountByAverage(decimal totalDiscount, int productCount)
        {
            if (productCount <= 0)
                throw new MSGException("商品数量必须大于0");

            if (totalDiscount <= 0)
                return [.. Enumerable.Repeat(0m, productCount)];

            decimal[] discounts = new decimal[productCount];

            // 计算每个商品应分配的基础优惠（保留两位小数）
            decimal baseDiscount = Math.Round(totalDiscount / productCount, 2, MidpointRounding.ToEven);

            // 先给每个商品分配基础优惠
            for (int i = 0; i < productCount; i++)
            {
                discounts[i] = baseDiscount;
            }

            // 计算已分配的总优惠
            decimal allocatedTotal = discounts.Sum();

            // 计算剩余未分配的优惠
            decimal remainder = totalDiscount - allocatedTotal;

            // 将剩余优惠全部加到最后一个商品
            if (remainder != 0 && productCount > 0)
            {
                discounts[productCount - 1] += remainder;
            }

            return discounts;
        }
    }
}
